package com.changzhi.service.impl;

import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.changzhi.common.constans.RedisConstans;
import com.changzhi.common.util.DateUtil;
import com.changzhi.common.util.LocalDateTimeUtils;
import com.changzhi.ldyl.model.*;
import com.changzhi.mapper.*;
import com.changzhi.service.UserGiftDayService;
import com.changzhi.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author huangrc
 * @since 2020-11-26
 */
@Slf4j
@Service
public class UserGiftDayServiceImpl extends ServiceImpl<UserGiftDayMapper, UserGiftDay> implements UserGiftDayService {

	@Resource
	private FirstRecordMapper firstRecordMapper;
	@Resource
	private UserGiftDayMapper userGiftDayMapper;
	@Resource
	private UserWalletMapper userWalletMapper;
	@Resource
	private UserAccountBookMapper userAccountBookMapper;
	@Resource
	private FamilySignedSettlementMapper familySignedSettlementMapper;
	@Resource
	private UserGiftMapper userGiftMapper;
	@Resource
	private ChatChannelMapper chatChannelMapper;
	@Resource
	private UserInvitationAwardMapper userInvitationAwardMapper;

	@Resource
	private UserInvitationConfigMapper userInvitationConfigMapper;
	@Resource
	private ChatChannelShareRatioConfigMapper chatChannelShareRatioConfigMapper;
	@Autowired
	private RedisUtil redisUtil;

	@Value("${application.name}")
	private String appName;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void doMqDataByHandler(UserGift userGift) {
		if(userGift.getTotalGiftValue() == 0){
			return;
		}
		doUserGiftDay(userGift);
		if ("Fizz".equals(appName)){
			handleGiftIncome(userGift);
		}
	}

	@Override
	public void repairGiftDay(String startDateStr, String endDateStr){
		long s = System.currentTimeMillis();
		LocalDate startDate = StringUtils.isBlank(startDateStr) ? LocalDate.now().minusDays(10) : DateUtil.stringToLocalDate(startDateStr);
		LocalDate endDate = StringUtils.isBlank(endDateStr) ? LocalDate.now() : DateUtil.stringToLocalDate(endDateStr);
		while (startDate.isEqual(endDate) || startDate.isBefore(endDate)){
			String startTime = startDate.toString() + " 00:00:00";
			String endTime = startDate.toString() + " 23:59:59";
			List<UserGift> userGifts = userGiftMapper.selectGroupByUserId(startTime, endTime);
			for (UserGift userGift : userGifts) {
				LambdaQueryWrapper<UserGiftDay> wrapper = new LambdaQueryWrapper<>();
				wrapper.eq(UserGiftDay::getChannelId, userGift.getChannelId()).eq(UserGiftDay::getUserId, userGift.getUserId()).eq(UserGiftDay::getCreateDate, startDate);
				UserGiftDay giftDay = userGiftDayMapper.selectOne(wrapper);
				if(giftDay == null){
					UserGiftDay userGiftDay = new UserGiftDay();
					userGiftDay.setChannelId(userGift.getChannelId());
					userGiftDay.setUserId(userGift.getUserId());
					userGiftDay.setTotalGiftValue(userGift.getTotalGiftValue());
					userGiftDay.setCreateDate(userGift.getCreateTime().toLocalDate());
					userGiftDay.setCreateTime(LocalDateTime.now());
					userGiftDay.setUpdateTime(LocalDateTime.now());
					userGiftDay.setBindChannelId(getBindChannelId(userGift.getChannelId(), userGift.getUserId()));
					userGiftDayMapper.insert(userGiftDay);
					log.error("修复问题数据，插入userGiftDay={}", JSON.toJSONString(userGiftDay));
				}else{
					if(giftDay.getTotalGiftValue().equals(userGift.getTotalGiftValue())){
						continue;
					}
					UserGiftDay userGiftDay = new UserGiftDay();
					userGiftDay.setId(giftDay.getId());
					userGiftDay.setTotalGiftValue(userGift.getTotalGiftValue());
					userGiftDay.setUpdateTime(LocalDateTime.now());
					userGiftDayMapper.updateById(userGiftDay);
					log.warn("修复问题数据，更新userGiftDay={},userGift={}", JSON.toJSONString(userGiftDay),JSON.toJSONString(userGift));
				}
			}
			log.warn("============进度 :startDate={}", startDate);
			startDate = startDate.plusDays(1);
		}
		log.error("============修复礼物天数据完成,耗时：{}", System.currentTimeMillis() - s);
	}

	@Override
	public void repairFirstInfo(String startDateStr) {
		long s = System.currentTimeMillis();
		LocalDate startDate = StringUtils.isBlank(startDateStr) ? LocalDate.now() : DateUtil.stringToLocalDate(startDateStr);
		while (startDate.isEqual(LocalDate.now()) || startDate.isBefore(LocalDate.now())){
			String startTime = startDate.toString() + " 00:00:00";
			String endTime = startDate.toString() + " 23:59:59";
			List<Long> giftIdList = userGiftMapper.selectGroupByFirst(startTime, endTime);
			LambdaQueryWrapper<UserGift> wrapper = new LambdaQueryWrapper<>();
			wrapper.in(UserGift::getId, giftIdList).orderByAsc(UserGift::getId);
			List<UserGift> userGifts = userGiftMapper.selectList(wrapper);
			for (UserGift userGift : userGifts) {
				LambdaQueryWrapper<FirstRecord> firstRecordWrapper = new LambdaQueryWrapper<>();
				firstRecordWrapper.eq(FirstRecord::getUserId, userGift.getUserId()).eq(FirstRecord::getType, 0);
				FirstRecord firstRecord = firstRecordMapper.selectOne(firstRecordWrapper);
				if (firstRecord == null) {
					firstRecord = new FirstRecord();
					firstRecord.setCreateTime(userGift.getCreateTime());
					firstRecord.setAmount(userGift.getTotalGiftValue());
					firstRecord.setChannelId(userGift.getChannelId());
					firstRecord.setType(0);
					firstRecord.setUserId(userGift.getUserId());
					firstRecord.setChannelId(userGift.getChannelId());
					firstRecord.setBindChannelId(getBindChannelId(userGift.getChannelId(),userGift.getUserId()));
					firstRecordMapper.insert(firstRecord);
					log.error("repairFirst修复问题数据【插入】，firstRecord={}", JSON.toJSONString(firstRecord));
				} else {
					if(firstRecord.getCreateTime().isEqual(userGift.getCreateTime()) || firstRecord.getCreateTime().isBefore(userGift.getCreateTime())){
						continue;
					}
					FirstRecord record = new FirstRecord();
					record.setId(firstRecord.getId());
					record.setCreateTime(userGift.getCreateTime());
					record.setAmount(userGift.getTotalGiftValue());
					firstRecordMapper.updateById(record);
					log.error("repairFirst修复问题数据【更新】更新前={}更新后={}，，firstRecord={},userGift={}", JSON.toJSONString(firstRecord),JSON.toJSONString(record),JSON.toJSONString(userGift));
				}
			}
			log.error("============repairFirst进度 :startDate={}", startDate);
			startDate = startDate.plusDays(1);
		}
		log.error("============repairFirst修复礼物天数据完成,耗时：{}", System.currentTimeMillis() - s);
	}




	//按天统计送礼
	private void doUserGiftDay(UserGift userGift){
		Integer totalGiftValue = userGift.getTotalGiftValue();
		String channelId = userGift.getChannelId();
		String userId = userGift.getUserId();
		String localDate = userGift.getCreateTime().toLocalDate().toString();
		String key = RedisConstans.GIFT_DAT + channelId + userId + localDate;
		UserGiftDay userGiftDay = redisUtil.get(key);
		log.info("methodName:doUserGiftDay, key = {}", key);
		//插入
		if(userGiftDay == null){
			LambdaQueryWrapper<UserGiftDay> wrapper = new LambdaQueryWrapper();
			wrapper.eq(UserGiftDay::getChannelId, channelId).eq(UserGiftDay::getUserId, userId).eq(UserGiftDay::getCreateDate, localDate);
			UserGiftDay record = userGiftDayMapper.selectOne(wrapper);
			if(record == null){
				userGiftDay = new UserGiftDay();
				userGiftDay.setChannelId(channelId);
				userGiftDay.setUserId(userId);
				userGiftDay.setTotalGiftValue(totalGiftValue);
				userGiftDay.setCreateDate(userGift.getCreateTime().toLocalDate());
				userGiftDay.setBindChannelId(getBindChannelId(userGift.getChannelId(), userGift.getUserId()));
				userGiftDayMapper.insertIgnore(userGiftDay);
				redisUtil.set(key, userGiftDay, RedisConstans.TWO_DAY);
				return;
			} else {
				userGiftDay = record;
			}
		}
		//更新
		userGiftDay.setTotalGiftValue(totalGiftValue);
		userGiftDayMapper.addGiftValue(userGiftDay);
	}


	public long differGiftValue(){
		LocalDateTime now = LocalDateTime.now();
		LocalDate localDate = now.toLocalDate();
		//礼物表求和
		Long value1 = userGiftMapper.selectValueSum(localDate, now);
		//天礼物求和
		Long value2 = userGiftDayMapper.selectValueSum(localDate);
		if(value1 == null || value2 == null){
			return 0L;
		}
		long differValue = value1 - value2;
		log.warn("methodName:differGiftValue, 时间={}, {} - {} = {}", DateUtil.localDateTimeToString(now), value1, value2, differValue);
		redisUtil.set(RedisConstans.GIFT_DAY_DIFFER + now.toString(), differValue, RedisConstans.ONE_DAY);
		return differValue;
	}


	private String getBindChannelId(String channelId, String userId){
		//邀请查询
		String inviterUserId = "";
		LambdaQueryWrapper<UserInvitationAward> inviteWrapper = new LambdaQueryWrapper<>();
		inviteWrapper.eq(UserInvitationAward::getUserId, userId).last("limit 1");
		UserInvitationAward invitationAward = userInvitationAwardMapper.selectOne(inviteWrapper);
		if (invitationAward != null && invitationAward.getInviterUserId() != null) {
			if(StringUtils.isNotBlank(invitationAward.getSkipChannelId())){
				return invitationAward.getSkipChannelId();
			}
			inviterUserId = invitationAward.getInviterUserId();
		}
		//跳转房间查询
		String bindChannelId = "";
		if(StringUtils.isNotBlank(inviterUserId)){
			LambdaQueryWrapper<UserInvitationConfig> configWrapper = new LambdaQueryWrapper<>();
			configWrapper.eq(UserInvitationConfig::getUserId, invitationAward.getInviterUserId()).last("limit 1");
			UserInvitationConfig invitationConfig = userInvitationConfigMapper.selectOne(configWrapper);
			if (invitationConfig != null && StringUtils.isNotBlank(invitationConfig.getSkipChannelId())) {
				String skipChannelId = invitationConfig.getSkipChannelId();
				if(channelId.equals(skipChannelId)){
					bindChannelId = channelId;
				}
			}
		}
		return bindChannelId;
	}

	//记录用户第一次送礼
	private void doFirstGiftRecord(UserGift userGift){
		LambdaQueryWrapper<FirstRecord> wrapper = new LambdaQueryWrapper();
		wrapper.eq(FirstRecord::getUserId, userGift.getUserId()).eq(FirstRecord::getType, 0);
		FirstRecord record = firstRecordMapper.selectOne(wrapper);
		if (record != null) {
			return;
		}
		FirstRecord firstRecord = new FirstRecord();
		firstRecord.setUserId(userGift.getUserId());
		firstRecord.setChannelId(userGift.getChannelId());
		firstRecord.setType(0);
		firstRecord.setAmount(userGift.getTotalGiftValue());
		firstRecord.setCreateTime(userGift.getCreateTime());
		firstRecord.setBindChannelId(getBindChannelId(userGift.getChannelId(),userGift.getUserId()));
		try {
			firstRecordMapper.insertIgnore(firstRecord);
		} catch (Exception e) {
			log.error("methodName:firstGiftRecord,param={},error={}", JSON.toJSONString(userGift), e.getMessage());
			e.printStackTrace();
		}
	}
	//是否首天
	private Integer getFirstDay(UserGift userGift){
		Integer firstDay = 0;
		LambdaQueryWrapper<UserGiftDay> queryWrapper = new LambdaQueryWrapper();
		queryWrapper.eq(UserGiftDay::getChannelId, userGift.getChannelId()).eq(UserGiftDay::getUserId, userGift.getUserId());
		queryWrapper.orderByAsc(UserGiftDay::getCreateDate).last("limit 1");
		UserGiftDay giftRecord = userGiftDayMapper.selectOne(queryWrapper);
		if(giftRecord == null || giftRecord.getCreateDate().isEqual(userGift.getCreateTime().toLocalDate())){
			firstDay = 1;
		}
		return firstDay;
	}

	private void handleGiftIncome(UserGift userGift){
		String channelId = userGift.getChannelId();
		if (channelId != null && !"".equals(channelId)){
			//查询房间分成比例
			ChatChannelShareRatioConfig shareRatioConfig = chatChannelShareRatioConfigMapper.selectOne(new LambdaQueryWrapper<ChatChannelShareRatioConfig>()
							.eq(ChatChannelShareRatioConfig::getChannelId, channelId).eq(ChatChannelShareRatioConfig::getStatus, 1));
			if (shareRatioConfig != null){
				//主播分成
				BigDecimal anchorShareRatio = shareRatioConfig.getAnchorShareRatio();
				UserSettlement anchorUserSettlement = createUserSettlement(anchorShareRatio, 1, userGift);
				handleShareIncome(anchorUserSettlement);
				//房间分成
				BigDecimal hostShareRatio = shareRatioConfig.getHostShareRatio();
				UserSettlement hostUserSettlement = createUserSettlement(hostShareRatio, 2, userGift);
				handleShareIncome(hostUserSettlement);
			}
		}

	}

	/**
	 * 创建收益记录，原逻辑是批量查询然后插入数据库
	 * @param shareRatio 分成比例
	 * @param type 厅主分成1:主播;2:房主
	 * @param userGift 礼物明细
	 */
	private UserSettlement createUserSettlement(BigDecimal shareRatio, Integer type, UserGift userGift){
		UserSettlement userSettlement = new UserSettlement();
		userSettlement.setId(userGift.getId());
		userSettlement.setUserId(userGift.getTargetId());
		//如果是厅主收益统计获取厅的厅主ID
		if (type == 2){
			ChatChannel chatChannel = chatChannelMapper.selectOne(new LambdaQueryWrapper<ChatChannel>()
					.eq(ChatChannel::getChannelId, userGift.getChannelId()));
			userSettlement.setUserId(chatChannel.getOwnerId());
		}
		userSettlement.setTotalGiftValue(userGift.getTotalGiftValue());

		BigDecimal income = shareRatio.multiply(BigDecimal.valueOf(userGift.getTotalGiftValue()));
		Integer totalIncome = income.intValue();
		userSettlement.setTotalIncome(totalIncome);
		userSettlement.setTotalIncomeDecimal(income.subtract(BigDecimal.valueOf(totalIncome)));
		userSettlement.setShareRatio(shareRatio);
		userSettlement.setType(type);
		userSettlement.setCreateTime(LocalDateTime.now());
		return userSettlement;
	}

	/**
	 * 处理收益记录
	 * @param userSettlement 收益记录
	 */
	private void handleShareIncome(UserSettlement userSettlement){
		//查询用户钱包信息
		LambdaQueryWrapper<UserWallet> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(UserWallet::getUserId, userSettlement.getUserId());
		wrapper.last("limit 1");
		UserWallet userWallet = userWalletMapper.selectOne(wrapper);

		//保存用户账户变动记录
		UserAccountBook accountBook = new UserAccountBook();
		accountBook.setCurrencyType(0);
		accountBook.setOrderId(userSettlement.getId().toString());
		accountBook.setAccountTitle("收益结算");
		accountBook.setReceivingAccount(userSettlement.getUserId());
		accountBook.setReceivingAmount(userSettlement.getTotalIncome());
		accountBook.setReceivingAccountTotal(userWallet.getDiamondsAmount());
		accountBook.setReceivingAccountBalance(userWallet.getDiamondsAmount() + userSettlement.getTotalIncome());
		accountBook.setCreateTime(LocalDateTime.now());
		userAccountBookMapper.insert(accountBook);

		// 房主分成
		Integer familyChannelCrystal = 0;
		BigDecimal familyChannelCrystalDecimal = BigDecimal.ZERO;
		if (userSettlement.getType() == 2) {
			saveFamilySignedSettlement(userSettlement);
			familyChannelCrystal = userSettlement.getTotalIncome();
			familyChannelCrystalDecimal = userSettlement.getTotalIncomeDecimal();
			BigDecimal totalIncomeDecimalChannel = NumberUtil.add(userSettlement.getTotalIncomeDecimal(), userWallet.getFamilyChannelCrystalDecimal());
			if (totalIncomeDecimalChannel.compareTo(BigDecimal.ONE) >= 0) {
				familyChannelCrystal = familyChannelCrystal + 1;
				familyChannelCrystalDecimal = NumberUtil.sub(totalIncomeDecimalChannel, BigDecimal.ONE);
			}
		}

		//礼物总收益
		Integer totalIncome = userSettlement.getTotalIncome();
		//钻石收益小数部分
		BigDecimal totalIncomeDecimal = NumberUtil.add(userSettlement.getTotalIncomeDecimal(), userWallet.getCrystalAmountDecimal());
		//如果钻石收益大于1，则将1加到收益中，并将钻石收益余下小数保存到钱包小数部分
		if (totalIncomeDecimal.compareTo(BigDecimal.ONE) >= 0) {
			totalIncome = totalIncome + 1;
			totalIncomeDecimal = NumberUtil.sub(totalIncomeDecimal, BigDecimal.ONE);
		} else {
			totalIncomeDecimal = userSettlement.getTotalIncomeDecimal();
		}

		//更新用户钱包
		userWalletMapper.updateCrystalAmount(userSettlement.getUserId(), totalIncome,totalIncomeDecimal, familyChannelCrystal,familyChannelCrystalDecimal);
	}

	/**
	 * 保存家族签约房间结算数据
	 * @param userSettlement 收益记录
	 */
	private void saveFamilySignedSettlement(UserSettlement userSettlement){
		//查询当前日期
		String dateStr = DateUtil.formatDate(new Date(), DateUtil.PATTERN_YYYY_MM_DD_NC);
		LocalDate startDate = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
		LocalDateTime nowDateTime = LocalDateTime.now();
		QueryWrapper<FamilySignedSettlement> queryWrapper = new QueryWrapper<FamilySignedSettlement>();
		queryWrapper.eq(FamilySignedSettlement.FAMILY_ID, userSettlement.getFamilyId());
		queryWrapper.eq(FamilySignedSettlement.USER_ID, userSettlement.getSignedUserId());
		queryWrapper.eq(FamilySignedSettlement.CREATE_DATE, startDate).last("limit 1");
		//查询家族用户今日收益，如果存在就修改，不存在就添加
		FamilySignedSettlement signedSettlement = familySignedSettlementMapper.selectOne(queryWrapper);
		if (signedSettlement == null) {
			signedSettlement = new FamilySignedSettlement();
			signedSettlement.setFamilyId(userSettlement.getFamilyId());
			signedSettlement.setOwnerUserId(userSettlement.getUserId());
			signedSettlement.setUserId(userSettlement.getSignedUserId());
			signedSettlement.setChannelId(userSettlement.getSignedChannelId());
			signedSettlement.setTotalGiftValue(userSettlement.getTotalGiftValue());
			signedSettlement.setTotalIncome(userSettlement.getTotalIncome());
			signedSettlement.setCreateDate(startDate);
			signedSettlement.setUpdateTime(nowDateTime);
			signedSettlement.setCreateTime(nowDateTime);
			familySignedSettlementMapper.insert(signedSettlement);
		} else {
			signedSettlement.setTotalGiftValue(signedSettlement.getTotalGiftValue() + userSettlement.getTotalGiftValue());
			signedSettlement.setTotalIncome(signedSettlement.getTotalIncome() + userSettlement.getTotalIncome());
			signedSettlement.setUpdateTime(nowDateTime);
			familySignedSettlementMapper.updateById(signedSettlement);
		}
	}
}
